﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX;
using SlimDX.Direct3D11;

namespace EikonLeap
{
    public class Scene
    {
        public Scene()
        {
            WorldTransform = Matrix.Identity;
        }

        public float angleY = 0.0f;
        public float angleX = 0.0f;
        private float omegaX = 0.0f;
        private float omegaY = 0.0f;
        private const float twoPI = (float)Math.PI * 2.0f;
        private const float pi = (float)Math.PI;
        private float ClampAngle(float angle)
        {
            while (angle < 0.0f)
                angle = twoPI + angle;
            while (angle > twoPI)
                angle = angle - twoPI;

            return angle;
        }

        public void Swipe(float x, float y)
        {
            omegaY += x;
            omegaX += y;
        }

        public void Update(double elapsedTime, Input input)
        {
            const float friction = 0.000003f;
            var mouse = input.Mouse;
            var mouseState = mouse.GetCurrentState();
            if (mouseState.IsPressed(0))
            {
                Swipe(mouseState.X / 70000.0f, mouseState.Y / 70000.0f);
            }

            Vector2 cursorpos = input.CursorPosition;


            if (input.SweepSpeed != 0.0f)
            {
                Swipe(input.SweepSpeed, 0.0f);
                input.SweepSpeed = 0.0f;
            }
            //Test intersection
            float cursorX = cursorpos.X;
            float cursorY = cursorpos.Y;
            SceneObject selectedObj = null;
            foreach (var obj in m_objects)
            {
                float d;
                obj.Value.IsHighlighten = false;
                if (obj.Value.IntersectScreenSpace(cursorX, cursorY, out d))
                {
                    obj.Value.IsHighlighten = true;
                    selectedObj = obj.Value;
                }
            }

            if (selectedObj != null)
            {
                (selectedObj as ScreenPlate).zoom = input.m_zoom;
            }

            angleX += omegaX;
            angleY += omegaY;

            if (omegaX != 0)
                omegaX = (omegaX < 0) ? omegaX + friction : omegaX - friction;
            if (omegaY != 0)
                omegaY = (omegaY < 0) ? omegaY + friction : omegaY - friction;
            if (Math.Abs(omegaX) < 0.0001) omegaX = 0;
            if (Math.Abs(omegaY) < 0.0001) omegaY = 0;
            //angleX = ClampAngle(angleX);
            //angleY = ClampAngle(angleY);
            

            //angleX += 0.001f * (float)elapsedTime;
            WorldTransform = Matrix.RotationY(angleY) * Matrix.RotationX(angleX);

            foreach (var obj in m_objects)
            {
                obj.Value.Update(elapsedTime);
            }
        }

        public void AddObject(string key, SceneObject obj)
        {
            m_objects.Add(key, obj);
            obj.m_scene = this;
        }

        public Dictionary<string, SceneObject> Objects
        {
            get
            {
                return m_objects;
            }
        }

        public Dictionary<string, Camera> Cameras = new Dictionary<string,Camera>();
        public void SetActiveCamera(string name)
        {
            ActiveCamera = Cameras[name];
        }

        public Camera ActiveCamera
        {
            get
            {
                if (m_activeCamera == null)
                {
                    SetActiveCamera(Cameras.First().Key);
                }
                return m_activeCamera;
            }

            set
            {
                m_activeCamera = value;
            }
        }
        private Camera m_activeCamera;
        public Renderer Renderer { get; set; }
        public Matrix WorldTransform { get; set; }
        Dictionary<string, SceneObject> m_objects = new Dictionary<string,SceneObject>();
    }
}
    